home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / Form / Sources / Frame.cpp < prev    next >
Encoding:
Text File  |  1996-09-17  |  18.8 KB  |  620 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                Frame.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Copyright:            (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "Form.hpp"
  11.  
  12. #ifndef FRAME_H
  13. #include "Frame.h"
  14. #endif
  15.  
  16. #ifndef CONTENT_H
  17. #include "Content.h"
  18. #endif
  19.  
  20. #ifndef DIALOG_H
  21. #include "Dialog.h"
  22. #endif
  23.  
  24. #ifndef PART_H
  25. #include "Part.h"
  26. #endif
  27.  
  28. #ifndef VIEW_H
  29. #include "View.h"
  30. #endif
  31.  
  32. #ifndef EDITCMD_H
  33. #include "EditCmd.h"
  34. #endif
  35.  
  36. // ----- Framework Layer -----
  37.  
  38. #ifndef FWBUTTON_H
  39. #include "FWButton.h"
  40. #endif
  41.  
  42. #ifndef FWTABBER_H
  43. #include "FWTabber.h"
  44. #endif
  45.  
  46. #ifndef FWIDLE_H
  47. #include "FWIdle.h"
  48. #endif
  49.  
  50. #ifndef FWUTIL_H
  51. #include "FWUtil.h"
  52. #endif
  53.  
  54. #ifndef FWSCROLR_H
  55. #include "FWScrolr.h"
  56. #endif
  57.  
  58. #ifndef FWSCLBAR_H
  59. #include "FWSclBar.h"
  60. #endif
  61.  
  62. #ifndef FWGROWBX_H
  63. #include "FWGrowBx.h"
  64. #endif
  65.  
  66. #ifndef FWBUTTON_H
  67. #include "FWButton.h"
  68. #endif
  69.  
  70. #ifndef FWPOPUP_H
  71. #include "FWPopup.h"
  72. #endif
  73.  
  74. #ifndef FWCONTXT_H
  75. #include "FWContxt.h"
  76. #endif
  77.  
  78. #ifndef FWPRHDLR_H
  79. #include "FWPrHdlr.h"
  80. #endif
  81.  
  82. // ----- OS Layer -----
  83.  
  84. #ifndef FWMENU_H
  85. #include "FWMenu.h"
  86. #endif
  87.  
  88. #ifndef FWEVENT_H
  89. #include "FWEvent.h"
  90. #endif
  91.  
  92. #ifndef FWALERT_H
  93. #include "FWAlert.h"
  94. #endif
  95.  
  96. #ifndef SLMixOS_H
  97. #include "SLMixOS.h"
  98. #endif
  99.  
  100. #ifndef FWCFMRES_H
  101. #include "FWCFMRes.h"
  102. #endif
  103.  
  104. #ifndef FWODMISC_H
  105. #include "FWODMisc.h"
  106. #endif
  107.  
  108. #ifndef FWRESOUR_H
  109. #include "FWResour.h"
  110. #endif
  111.  
  112. // ----- Graphic Includes -----
  113.  
  114. #ifndef FWRECT_H
  115. #include "FWRect.h"
  116. #endif
  117.  
  118. #ifndef FWTXTBOX_H
  119. #include "FWTxtBox.h"
  120. #endif
  121.  
  122. #ifndef FWRECSHP_H
  123. #include "FWRecShp.h"
  124. #endif
  125.  
  126. #ifndef FWPICSHP_H
  127. #include "FWPicShp.h"        
  128. #endif
  129.  
  130. #ifndef FWRGNSHP_H
  131. #include "FWRgnShp.h"        
  132. #endif
  133.  
  134. #ifndef FWLINSHP_H
  135. #include "FWLinShp.h"        
  136. #endif
  137.  
  138. // ----- Foundation Layer -----
  139.  
  140. #ifndef FWNOTIFN_H
  141. #include "FWNotifn.h"
  142. #endif
  143.  
  144. #ifndef FWNOTDEF_H
  145. #include "FWNotDef.h"
  146. #endif
  147.  
  148. // ----- PPob View Support -----
  149.  
  150. #if FW_PPOB_VIEWS
  151. #include "FWPPobRd.h"
  152. #endif
  153.  
  154. // ----- MacApp View Support -----
  155.  
  156. #if FW_MACAPP_VIEWS
  157. #include "FWMARead.h"
  158. #endif
  159.  
  160. //========================================================================================
  161. // Runtime Informations
  162. //========================================================================================
  163.  
  164. #ifdef FW_BUILD_MAC
  165. #pragma segment odfform
  166. #endif
  167.  
  168. FW_DEFINE_AUTO(CFormFrame)
  169. FW_DEFINE_CLASS_M2(CFormFrame, FW_CFrame, FW_MReceiver)
  170.  
  171. //========================================================================================
  172. // CFormFrame class
  173. //========================================================================================
  174.  
  175. //----------------------------------------------------------------------------------------
  176. // CFormFrame::CFormFrame
  177. //----------------------------------------------------------------------------------------
  178. CFormFrame::CFormFrame(Environment* ev, ODFrame* odFrame, FW_CPresentation* presentation, CFormPart* part)
  179.     : FW_CFrame(ev, odFrame, presentation, part),
  180.     fFormPart(part),
  181.     fIdler(NULL),
  182.     fViewTabber(NULL)
  183. {
  184.     // We must create an idler to see the caret blink in the text-edit views
  185.     fIdler = FW_NEW(FW_CIdler, (this, 15));
  186.     fIdler->RegisterIdle(ev);                
  187. }
  188.  
  189. //----------------------------------------------------------------------------------------
  190. // CFormFrame::~CFormFrame
  191. //----------------------------------------------------------------------------------------
  192.  
  193. CFormFrame::~CFormFrame()
  194. {
  195.     delete fIdler;
  196.     
  197.     // fViewTabber is deleted automatically because it's an attached event handler
  198. }
  199.  
  200. //----------------------------------------------------------------------------------------
  201. //    CFormFrame::PostCreateViewFromStream
  202. //----------------------------------------------------------------------------------------
  203. // PostCreateViewFromStream is called after subviews are created from resources.  
  204. // Implement initializations for this view that can't be done from a stream.
  205.  
  206. void CFormFrame::PostCreateViewFromStream(Environment* ev)
  207. {
  208.     // ----- Add a ViewTabber to the frame 
  209. #if FW_ODFRC_VIEWS || FW_MACAPP_VIEWS
  210.     fViewTabber = new FW_CViewTabber(ev, this); 
  211. #endif
  212.  
  213.     // ----- Additional processing for non-root (i.e. embedded) frames
  214.     if (IsRoot(ev) == false) 
  215.     {
  216.         // Remove the GrowBox (delete is enough to remove it from the subviews list)
  217.         FW_CView* growBox = FindViewByID(ev, kGrowBoxID);
  218.         delete growBox;
  219.         
  220.         // Shrink the scroll-bars to leave space for a 1 pixel border
  221.         // NOTE: It's against OpenDoc HI guidelines to keep scroll-bars in embedded frames
  222.         //         and also to have an embedded frame draw its own border! 
  223.         //         Drawing the border should be the responsability of the container.
  224.         //         ... We wanted this sample to be different.
  225.         
  226.         FW_CView* hSB = FindViewByID(ev, kHorzScrollBarID);
  227.         if (hSB)
  228.         {
  229.             FW_CPoint hSBLoc = hSB->GetLocation(ev);
  230.             hSBLoc.x += FW_kFixedPos1;
  231.             hSBLoc.y -= FW_kFixedPos1;
  232.             FW_CPoint hSBSize = hSB->GetSize(ev);
  233.             hSBSize.x -= FW_IntToFixed(2);
  234.             hSB->SetLocation(ev, hSBLoc, FW_kDontRedraw);
  235.             hSB->SetSize(ev, hSBSize, FW_kDontRedraw);
  236.         }
  237.         
  238.         FW_CView* vSB = FindViewByID(ev, kVertScrollBarID);
  239.         if (vSB)
  240.         {
  241.             FW_CPoint vSBLoc = vSB->GetLocation(ev);
  242.             vSBLoc.x -= FW_kFixedPos1;
  243.             vSBLoc.y += FW_kFixedPos1;
  244.             FW_CPoint vSBSize = vSB->GetSize(ev);
  245.             vSBSize.y -= FW_IntToFixed(2);
  246.             vSB->SetLocation(ev, vSBLoc, FW_kDontRedraw);
  247.             vSB->SetSize(ev, vSBSize, FW_kDontRedraw);
  248.         }
  249.     }
  250.         // now that views have been created, tell the content
  251.         // object to register interests
  252.     CFormContent* content = (CFormContent*)GetFormPart()->GetContent(ev);
  253.     content->AddViewInterests(ev, this);
  254.     content->ExportToViews(ev, this);
  255. }
  256.  
  257. //----------------------------------------------------------------------------------------
  258. // CFormFrame::CreateSubViews
  259. //----------------------------------------------------------------------------------------
  260. // The subviews created for this frame are:
  261. //
  262. //   CFormFrame 
  263. //         |_____ grow box      (only for root frame)
  264. //         |
  265. //         |_____ horzSB         (horizontal scrollbar)
  266. //         |_____ vertSB         (vertical scrollbar)
  267. //         |
  268. //         |_____ contentView     (scrolling form)
  269. //                      |
  270. //                    |_____ <Several Controls, Edit views and 1 list box>...
  271. //                                      
  272. // This sample shows how to create views in 4 different methods
  273. // 1) Using the ODF resource format in Views.fr --> flag FW_ODFRC_VIEWS
  274. // 2) Using a PPob resource in ODFForm.ppob --> flag FW_PPOB_VIEWS
  275. // 3) Using a MacApp resource in ODFForm.rsrc --> flag FW_MACAPP_VIEWS
  276. // 4) Or doing it by hand if you prefer! --> 
  277.  
  278. void CFormFrame::CreateSubViews(Environment* ev)
  279. {        
  280. #if FW_ODFRC_VIEWS
  281.     // Load views from ODFRC resources that were compiled from Views.fr
  282.     CreateSubViewsFromResource(ev, kFormView);
  283.  
  284. #elif FW_PPOB_VIEWS
  285.     // Load views from PPob resource.  
  286.     // - Pass NULL as receiver arg if you don't want to link controls automatically
  287.     // - There is not much error handling to do here for a finished part. See the
  288.     //   code of the ViewTester part for more info on error handling.
  289.     FW_PlatformError error = 
  290.         FW_CPPobReader::CreateSubViewsFromPPobResource(
  291.                                     ev, 
  292.                                     kFormView,     // 'PPob' view id
  293.                                     this,         // frame is the root view
  294.                                     this,         // frame is receiver for all controls
  295.                                     FW_CPPobReader::kPartOnly); // use part's resources
  296.     
  297. #elif FW_MACAPP_VIEWS
  298.     // Load views from MacApp resource.  See same comments above
  299.     FW_PlatformError error = 
  300.         FW_CMacAppReader::CreateSubViewsFromMacAppResource(
  301.                                     ev, 
  302.                                     kFormView,  // MacApp 'View' id
  303.                                     this,         // frame is the root view
  304.                                     this,         // frame is receiver for all controls
  305.                                     FW_CMacAppReader::kPartOnly); // use part's resources
  306.  
  307. #else
  308.     // This code is compiled if you didn't define any of the 3 FW_XXX_VIEWS flags
  309.     // above, i.e. it shows how to create views by program instead of using resources
  310.     // See also CFormView::CreateSubViews().
  311.     
  312.     FW_CRect frameRect = GetBounds(ev);  
  313.     FW_CRect contentRect;    // frame rect without scroll-bars
  314.     GetContentRect(ev, contentRect);
  315.     
  316.     if (IsRoot(ev)) 
  317.     {
  318.         // ----- Create the GrowBox only in root frame
  319.         FW_CGrowBox* growBox = new FW_CGrowBox(ev, this, 0, contentRect.BotRight());
  320.     }
  321.     else
  322.     {
  323.         // ----- Leave space to draw 1 pixel border in non-root frames
  324.         frameRect.Inset(FW_kFixedPos1);
  325.     }
  326.  
  327.     // ----- Create the vertical & horizontal scroll bars inside the frame
  328.     FW_CRect vertSbRect(contentRect.right, frameRect.top - FW_kFixedPos1, 
  329.                     frameRect.right + FW_kFixedPos1, contentRect.bottom + FW_kFixedPos1);
  330.     FW_CScrollBar* vertSB = FW_NEW(FW_CScrollBar, (ev, this, 0, vertSbRect));
  331.     
  332.     FW_CRect horzSbRect(frameRect.left - FW_kFixedPos1, contentRect.bottom, 
  333.                     contentRect.right + FW_kFixedPos1, frameRect.bottom + FW_kFixedPos1);
  334.     FW_CScrollBar* horzSB = FW_NEW(FW_CScrollBar, (ev, this, 0,horzSbRect));        
  335.  
  336.     // ----- Create the content view with the extent of the picture
  337.     //         (The content view's subviews are created later in CFormView::CreateSubViews)
  338.     FW_CRect    pictRect;
  339.     CFormView* contentView = new CFormView(ev, this, contentRect, kFormPict1, kFormPict2);
  340.     contentView->BecomeContentView(ev); 
  341.     
  342.     // ----- Create a scroller  (this must be done AFTER the content view)
  343.     FW_CScroller* scroller = FW_NEW(FW_CScrollBarScroller, (ev, this, horzSB, vertSB));
  344.     AdoptScroller(ev, scroller);
  345.     
  346.     // ----- Add a ViewTabber to the frame 
  347.     fViewTabber = new FW_CViewTabber(ev, this); 
  348. #endif
  349. }
  350.  
  351. //----------------------------------------------------------------------------------------
  352. // CFormFrame::GetContentRect
  353. //----------------------------------------------------------------------------------------
  354.  
  355. void CFormFrame::GetContentRect(Environment* ev, FW_CRect& rect)
  356. {
  357.     rect = GetBounds(ev);
  358.     
  359.     // Leave space to draw 1 pixel border in non-root frames
  360.     if (IsRoot(ev) == FALSE)
  361.         rect.Inset(FW_kFixedPos1);
  362.         
  363.     FW_CPoint sbSize = FW_CScrollBar::GetDefaultScrollBarSize();
  364.  
  365.     rect.right -= sbSize.x;
  366.     rect.bottom -= sbSize.y;
  367. }
  368.  
  369. //----------------------------------------------------------------------------------------
  370. // CFormFrame::Draw
  371. //----------------------------------------------------------------------------------------
  372.  
  373. void CFormFrame::Draw(Environment *ev, ODFacet* odFacet, ODShape* invalidShape)
  374. {
  375.     FW_CRect contentRect;
  376.     GetContentRect(ev, contentRect);
  377.     FW_CRect formRect(GetFrame(ev)->GetContentView(ev)->GetBounds(ev));
  378.     
  379.     FW_CViewContext vc(ev, this, odFacet, invalidShape);
  380.     
  381.     // Draw a gray background around the content view if it's smaller
  382.     if (formRect.right < contentRect.right || formRect.bottom < contentRect.bottom ) {
  383.  
  384.         // Draw outside the center view to avoid flashing 
  385.         FW_CAcquiredODShape aqPaneShape = ::FW_NewODShape(ev, contentRect);
  386.         FW_CAcquiredODShape aqCenterShape = ::FW_NewODShape(ev, formRect);
  387.         aqPaneShape->Subtract(ev, aqCenterShape);
  388.     
  389.         FW_CRegionShape::RenderRegion(vc, aqPaneShape, FW_kFill, FW_kRGBLightGray);
  390.     
  391.         // Draw a shadow frame around the content view
  392.         formRect.Inset(-FW_kFixedPos1,-FW_kFixedPos1);
  393.          FW_CRectShape::RenderRect(vc, formRect, FW_kFrame);
  394.          FW_CPoint p1(formRect.left, formRect.bottom);
  395.          FW_CPoint p2(formRect.right, formRect.bottom);
  396.          FW_CPoint p3(formRect.right, formRect.top);
  397.          if (formRect.bottom < contentRect.bottom - FW_kFixedPos1)
  398.              FW_CLineShape::RenderLine(vc, p1, p2);
  399.         if (formRect.right < contentRect.right - FW_kFixedPos1)
  400.              FW_CLineShape::RenderLine(vc, p2, p3);
  401.     }
  402.     
  403.     if (IsRoot(ev) == FALSE)
  404.     {
  405.         // Draw a 1 pixel border in non-root frames
  406.         FW_CRect frameRect = GetBounds(ev);        
  407.          FW_CRectShape::RenderRect(vc, frameRect, FW_kFrame);
  408.     }
  409. }
  410.  
  411. //----------------------------------------------------------------------------------------
  412. //    CFormFrame::FrameShapeChanged
  413. //----------------------------------------------------------------------------------------
  414.  
  415. void CFormFrame::FrameShapeChanged(Environment *ev)
  416. {
  417.     // By default a FW_CFrame view is not refreshed entirely when resized.
  418.     // You must decide if your content's appearance depends on the frame's size.
  419.     // If it doesn't you don't need to override FrameShapeChanged().
  420.     // Here it's a little bit tricky because the formView is centered inside the frame,
  421.     // so the only case where the content is fixed is when the frame is smaller than the
  422.     // formView, i.e. the formView is anchored to the topleft corner.
  423.  
  424.     // Check if the formView was anchored before resizing
  425.     FW_CRect contentRect;
  426.     GetContentRect(ev, contentRect);
  427.     FW_CSuperView* formView = GetFrame(ev)->GetContentView(ev);
  428.     FW_CPoint formTopLeft(formView->GetBounds(ev).TopLeft());
  429.     FW_Boolean    anchoredBefore = (contentRect.TopLeft() == formTopLeft) ? TRUE : FALSE;    
  430.  
  431.     // Resize the frame (this invalidates only the modified region)
  432.     FW_CFrame::FrameShapeChanged(ev);    
  433.     
  434.     // Check if the formView is anchored after resizing
  435.     GetContentRect(ev, contentRect);
  436.     formTopLeft = formView->GetBounds(ev).TopLeft();
  437.     FW_Boolean    anchoredAfter = (contentRect.TopLeft() == formTopLeft) ? TRUE : FALSE;    
  438.     
  439.     // Invalidate the whole frame if we need redraw outside the formview
  440.     if (!anchoredBefore || !anchoredAfter)
  441.         Invalidate(ev);
  442. }
  443.  
  444. //----------------------------------------------------------------------------------------
  445. //    CFormFrame::HandleNotification
  446. //----------------------------------------------------------------------------------------
  447.  
  448. void CFormFrame::HandleNotification(Environment* ev, const FW_CNotification& notification)
  449. {
  450.     // Handle notification messages for the registered controls.
  451.     // GetMessage() allows to switch on the type of notification.  For each message
  452.     // we can down-cast "notification" directly to the right subclass, without
  453.     // having to use RTTI, because the message is unique to that type.
  454.     
  455.     switch (notification.GetMessage()) 
  456.     {
  457.         case FW_kButtonPressedMsg: 
  458.         {
  459.             const FW_CControlNotification& controlNotification = 
  460.                                                     (FW_CControlNotification&) notification;
  461.  
  462.             // This frame has several active buttons, we must switch on the button id
  463.             ODID viewID = controlNotification.GetViewID(ev);
  464.             switch (viewID) 
  465.             {
  466.                 case kNoRadioID:
  467.                     // Show alert if "No" is being selected... and select "Yes" again :)
  468.                     if (controlNotification.GetControl(ev)->GetValue(ev) == 1)
  469.                     {
  470.                         // FW_Beep();
  471.                         FW_NoteAlert(FW_CString(), FW_CString(" We don't believe you! "));
  472.                         FW_CButton* yesButton = (FW_CButton*)FindViewByID(ev, kYesRadioID);
  473.                         yesButton->SetValue(ev, 1);
  474.                     }
  475.                     break;
  476.                     
  477.                 case kSubscribeButtonID:
  478.                     // Open modal dialog to pick a password
  479.                     OpenPasswordDialog(ev);
  480.                     break;
  481.                     
  482.                 case kAddButtonID:
  483.                 case kRemoveButtonID:
  484.                     // Add/Remove an item in the list box
  485.                     ModifyPlatformList(ev, viewID == kAddButtonID ? TRUE : FALSE);
  486.                     break;
  487.             }
  488.         } 
  489.         break;
  490.         
  491.         case FW_kListBoxDoubleClickedMsg:
  492.         {
  493.             const FW_CListBoxNotification& listBoxNotification = 
  494.                                                     (FW_CListBoxNotification&) notification;
  495.             
  496.             // Beep if we double-click on the first item
  497.             if (listBoxNotification.GetListBox(ev)->GetSelectedItem(ev) == 1)
  498.                 FW_Beep();
  499.         }
  500.         break;
  501.         
  502.         default:
  503.             FW_ASSERT("CFormFrame can't respond to this");
  504.             break;
  505.     }
  506. }
  507.  
  508. //----------------------------------------------------------------------------------------
  509. //    CFormFrame::OpenPasswordDialog
  510. //----------------------------------------------------------------------------------------
  511.  
  512. void CFormFrame::OpenPasswordDialog(Environment* ev)
  513. {
  514.     // position is not important here because we use FW_kStandardDialogPosition in the
  515.     // window style to center the dialog properly.
  516.     FW_CPoint    position(FW_kZeroPoint);
  517.     FW_CPoint    size(FW_IntToFixed(300), FW_IntToFixed(160));
  518.     
  519.     FW_WindowStyle style = FW_kStandardDialogPosition | FW_kHasCaption;
  520.  
  521.     FW_CPresentation* dialogPresentation = GetFormPart()->GetPwdDialogPresentation();
  522.     
  523.     // ----- Create new dialog window with the "Password" presentation -----
  524.     //
  525.     // Note: unlike the standard Mac Toolbox "ModalDialog" FW_CDialogFrame::NewModalDialog
  526.     //        returns right after creating the dialog.  Events are processed the same
  527.     //        way as any other OpenDoc frames, except that the modal focus is set.
  528.     //        (NewModalDialog can return NULL if the dialog creation failed because the 
  529.     //        modal focus could not be granted)
  530.     //
  531.     //        Here we use NewModalDialog() instead of NewAndShowModalDialog() because
  532.     //        we need to initialize a few things before opening the dialog
  533.         
  534.     CPwdDialogFrame* dialog = (CPwdDialogFrame*) FW_CDialogFrame::NewModalDialog(ev, 
  535.                             GetPart(ev),                // Your part
  536.                             dialogPresentation,         // Used in CFormPart::NewFrame
  537.                             size,                         // Window size
  538.                             position,                     // Window position
  539.                             style,                        // Make dialog moveable
  540.                             FW_CString("Password"));    // Title for moveable dialog
  541.     
  542.     if (dialog != NULL)
  543.     {                        
  544.         dialog->Initialize(ev, this);        
  545.         dialog->GetWindow(ev)->Show(ev);
  546.     }
  547. }
  548. //----------------------------------------------------------------------------------------
  549. //    CFormFrame::ModifyPlatformList
  550. //----------------------------------------------------------------------------------------
  551.  
  552. void CFormFrame::ModifyPlatformList(Environment* ev, FW_Boolean addItem)
  553. {
  554.     FW_CListBox* list = (FW_CListBox*)FindViewByID(ev, kPlatformListBoxID);
  555.     FW_ASSERT(list);
  556.     
  557.     if (addItem)
  558.     {
  559.         // Add a row after the last selected item or at the end.
  560.         short addIndex = 0;
  561.         short count = list->GetSelectionCount(ev);
  562.  
  563.         if (count > 0)
  564.         {
  565.             // We must retrieve the list of selected items in a dynamic array
  566.             short* const indexArray = new short[count];
  567.             
  568.             short read = list->GetSelectedItems(ev, count, indexArray);
  569.             FW_ASSERT(read == count);
  570.             
  571.             addIndex = indexArray[count - 1] + 1;
  572.             
  573.             delete indexArray;
  574.         }
  575.         
  576.         list->AddStringItem(ev, FW_CString("Macintosh"), addIndex);        
  577.         list->ScrollIntoView(ev, addIndex);
  578.     }
  579.     else 
  580.     {
  581.         // Remove the first selected item
  582.         short selectedItem = list->GetSelectedItem(ev);
  583.         if (selectedItem > 0)
  584.             list->DeleteItems(ev, selectedItem);
  585.  
  586.         // Update button's state
  587.         FW_CButton* rmButton = (FW_CButton*)FindViewByID(ev, kRemoveButtonID);
  588.         if (list->GetSelectedItem(ev) == 0)
  589.             rmButton->Disable(ev);
  590.     }
  591. }
  592.  
  593.  
  594. //----------------------------------------------------------------------------------------
  595. //    CFormFrame::NewPrintHandler
  596. //----------------------------------------------------------------------------------------
  597. // NewPrintHandler is all you need to support printing!
  598. // (You can also add a progress dialog resource as in ODF Draw's FWPrint.r but it's
  599. //  not necessary and not very useful with background printing)
  600.  
  601. FW_CPrintHandler* CFormFrame::NewPrintHandler(Environment* ev)
  602. {
  603. FW_UNUSED(ev);
  604.     // We use the base PrintHandler class for basic printing of the content view
  605.     // (See ODF Draw for a more advanced example)
  606.     return new FW_CPrintHandler(fFormPart, this);
  607. }
  608.  
  609.  
  610. //----------------------------------------------------------------------------------------
  611. //    CFormFrame::NewClipboardCommand
  612. //----------------------------------------------------------------------------------------
  613.  
  614. FW_CClipboardCommand* CFormFrame::NewClipboardCommand(Environment* ev, ODCommandID commandID)
  615. {
  616.     CEditViewCommand* cmd = FW_NEW(CEditViewCommand, (ev, commandID, this, FW_kCanUndo));
  617.     return cmd;
  618. }
  619.  
  620.